﻿using System;
using System.Collections.Generic;
using System.IO;

namespace TiaoTiaoCode.Common.ClassEntities
{
    /// <summary>
    /// 文件变化监听器
    /// </summary>
    public class TiaoTiaoFileWatcher
    {
        static Lazy<Dictionary<string, FileSystemWatcher>> _dicWatcher = new Lazy<Dictionary<string, FileSystemWatcher>>();

        /// <summary>
        /// 文件监听变化事件
        /// </summary>
        public event EventHandler<FileWacherChangedEventArgs>? OnFileWacherChanged;

        private static TiaoTiaoFileWatcher _instance = new TiaoTiaoFileWatcher();
        public static TiaoTiaoFileWatcher Instance => _instance;
        private TiaoTiaoFileWatcher() { }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="watcherName">文件监控名</param>
        /// <param name="watcherPath">监控路径</param>
        /// <param name="fileter">过滤方式</param>
        /// <param name="isInclude">是否包含子目录</param>
        public void Init(string watcherName, string watcherPath, string fileter, bool isInclude)
        {
            if (_dicWatcher.Value.ContainsKey(watcherName)) throw new Exception("已存在文件监控");

            var watcher = new FileSystemWatcher();

            watcher.BeginInit();

            watcher.Filter = fileter;
            watcher.IncludeSubdirectories = isInclude;
            watcher.EnableRaisingEvents = true;

            watcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite;
            watcher.Path = watcherPath;

            watcher.Changed += WatcherChanged;

            watcher.EndInit();

            _dicWatcher.Value.Add(watcherName, watcher);
        }

        /// <summary>
        /// 停止文件监控
        /// </summary>
        /// <param name="watcherName"></param>
        public void StopWatch(string watcherName)
        {
            if (!_dicWatcher.Value.ContainsKey(watcherName)) return;

            _dicWatcher.Value[watcherName].EnableRaisingEvents = false;
            _dicWatcher.Value[watcherName].Changed -= WatcherChanged;

            _dicWatcher.Value[watcherName].Dispose();

            _dicWatcher.Value.Remove(watcherName);
        }

        void WatcherChanged(object sender, FileSystemEventArgs e)
        {
            if (!(sender is FileSystemWatcher watcher)) return;

            //EnableRaisingEvents先关闭再打开，解决触发多次问题
            watcher.EnableRaisingEvents = false;

            OnFileWacherChanged?.Invoke(sender, new FileWacherChangedEventArgs { FileName = e.Name, FullPath = e.FullPath });

            watcher.EnableRaisingEvents = true;
        }
    }

    /// <summary>
    /// 文件变化事件
    /// </summary>
    public class FileWacherChangedEventArgs
    {
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; set; } = default!;

        /// <summary>
        /// 文件完整路径
        /// </summary>
        public string FullPath { get; set; } = default!;
    }
}
